package com.dfiov.cloud.msmtools.controller;

import cn.hutool.http.HttpRequest;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.dfiov.cloud.msmtools.entity.dto.*;
import com.dfiov.cloud.msmtools.entity.vo.balance.BalanceUsedResponse;
import com.dfiov.cloud.msmtools.entity.vo.msbluetooth.DkResult;
import com.dfiov.cloud.msmtools.entity.vo.msmtools.*;
import com.dfiov.cloud.msmtools.entity.vo.tspReport.AddDataByMonthAndVersionVo;
import com.dfiov.cloud.msmtools.entity.vo.tspReport.ExportDataByMonthAndVersionVo;
import com.dfiov.cloud.msmtools.mapper.entity.msdevice.VehicleWithSimResp;
import com.dfiov.cloud.msmtools.mapper.entity.msinfofeedback.NewFeedbackRecord;
import com.dfiov.cloud.msmtools.mapper.entity.msinfofeedback.PageResult;
import com.dfiov.cloud.msmtools.mapper.entity.msmtools.*;
import com.dfiov.cloud.msmtools.mapper.entity.msmtools.MsmtoolsColumnsDo;
import com.dfiov.cloud.msmtools.service.business.AuthService;
import com.dfiov.cloud.msmtools.service.feign.MsDeviceFeignClient;
import com.dfiov.cloud.msmtools.service.feign.MsunicomFeign;
import com.dfiov.cloud.msmtools.utils.JwtUtil;
import com.dfiov.cloud.msmtools.utils.RegexMatchesUtils;
import com.dfiov.cloud.msmtools.utils.ResponseUtils;
import com.ingeek.idp.sign.SignUtils;
import com.pateo.qingcloud.framework.common.base.BaseRestResponse;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.util.*;

@Slf4j
@RestController
@RequestMapping("/msmtools/tas")
public class AuthController {

    @Autowired
    private AuthService authService;

    @Autowired
    private MsunicomFeign msunicomFeign;

    @Autowired
    MsDeviceFeignClient msDeviceFeignClient;


    /*
    登录，生成token
     */
    @PostMapping("/auth/scanner/login")
    public HashMap<String,Object> scannerLogin(@RequestParam(value = "name") String name,@RequestParam(value = "pwd") String pwd) {

        HashMap<String,Object> res = new HashMap<>();
        res.put("state",false);

        //MD5加密
        ByteSource credentialsSalt = ByteSource.Util.bytes(name);
        Object obj = new SimpleHash("MD5", pwd, credentialsSalt, 1);
        String pwd2 = obj.toString();



        try {
            // 登录成功，生成token
            HashMap<String,Object> headMap = new HashMap<>();
            HashMap<String,String> claimMap = new HashMap<>();
            //claimMap.put("userId",Integer.toString(user.getId()));
            //claimMap.put("userName",user.getUserName());
            String accessToken = JwtUtil.getSign(headMap,claimMap,7);
            res.put("state",true);
            res.put("msg","登录成功");
            res.put("token",accessToken);


        } catch (UnknownAccountException e) {
            res.put("msg","用户名不存在");
        } catch (IncorrectCredentialsException e) {
            res.put("msg","密码错误");
        }
        return res;
    }

    /*
    获取token信息 authStr 如果是这种格式 Bearer token 需要把Bearer和空格替掉。
     */
    @PostMapping("/auth/scanner/checkToken")
    public Map<String, String> checkToken(@RequestHeader("Authorization")String authStr){
        DecodedJWT verify = JwtUtil.verify(authStr);
        Map<String, Claim> claims = verify.getClaims();
        Map<String,String> res = new HashMap<>();
        claims.forEach((key,value)-> res.put(key,value.asString()));
        return res;
    }

    /*
    拦截请求
     */
    @PostMapping("/auth/scanner/getCompanies")
    public Map<String,String> getCompanies(){
        Map<String,String> res = new HashMap<>();
        res.put("ali","阿里巴巴");
        res.put("baidu","百度");
        return  res;
    }

    /*
登录，生成token
 */
    @PostMapping("/userInfo/login")
    public HashMap<String,Object> login(@RequestBody AuthLoginVo authLoginVo) {

        log.info("/userInfo/login::"+ JSON.toJSONString(authLoginVo));
        String account = authLoginVo.getAccount();
        String pswd = authLoginVo.getPswd();

        HashMap<String,Object> res = new HashMap<>();

        //MD5加密
        ByteSource credentialsSalt = ByteSource.Util.bytes(account);
        Object obj = new SimpleHash("MD5", pswd, credentialsSalt, 1);
        String pwd2 = obj.toString();

        MsmtoolsUserInfoDo userByAccountAndPswd = authService.getUserByAccountAndPswd(account, pwd2);
        if(userByAccountAndPswd == null){
            log.info("账户或密码错误");
            res.put("status",1);
            res.put("msg","账户或密码错误");
            return res;
        }

        UserTokensDo userTokensByUserId = authService.getUserTokensByUserId(userByAccountAndPswd.getUserId());
        if(userTokensByUserId !=null  && userTokensByUserId.getExpireTime().after(new Date())){
            log.info("token未过期");
            res.put("status",0);
            res.put("msg","登录成功");
            res.put("token",userTokensByUserId.getToken());
            res.put("data",userByAccountAndPswd);
            return res;
        }

            // 登录成功，生成token
            HashMap<String,Object> headMap = new HashMap<>();
            HashMap<String,String> claimMap = new HashMap<>();
            claimMap.put("userId",String.valueOf(userByAccountAndPswd.getUserId()));
            claimMap.put("account",userByAccountAndPswd.getAccount());
            String accessToken = JwtUtil.getSign(headMap,claimMap,7);

        Date currentDate = new Date();
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(currentDate);
        calendar.add(Calendar.DAY_OF_MONTH, 7); // 加7天
        Date expireTime = calendar.getTime();

        UserTokensDo userTokensDo = new UserTokensDo();
        userTokensDo.setToken(accessToken);
        userTokensDo.setExpireTime(expireTime);
        userTokensDo.setUserId(userByAccountAndPswd.getUserId());
        int count = authService.saveUserTokens(userTokensDo);

            if(count>0){
                res.put("status",0);
                res.put("msg","登录成功");
                res.put("token",accessToken);
                res.put("data",userByAccountAndPswd);
                return res;
            }
        res.put("state",1);
        res.put("msg","登录失败");
        return res;
    }

    @PostMapping("/userInfo/saveUserTokens")
    public BaseRestResponse<Integer> saveUserTokens(@RequestBody UserTokensDo userTokensDo){
        // 登录成功，生成token
        HashMap<String,Object> headMap = new HashMap<>();
        HashMap<String,String> claimMap = new HashMap<>();
        claimMap.put("userId",String.valueOf(userTokensDo.getUserId()));
        claimMap.put("account","测试");
        String accessToken = JwtUtil.getSign(headMap,claimMap,7);

        Date currentDate = new Date();
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(currentDate);
        calendar.add(Calendar.DAY_OF_MONTH, 7); // 加7天
        Date expireTime = calendar.getTime();

        userTokensDo.setToken(accessToken);
        userTokensDo.setExpireTime(expireTime);
        int count = authService.saveUserTokens(userTokensDo);
        return ResponseUtils.success(count);
    }

    @PostMapping("/userInfo/saveUserInfo")
    public BaseRestResponse<Integer> saveUserInfo(@RequestBody MsmtoolsUserInfoDo msmtoolsUserInfoDo){
        authService.saveMsmtoolsUserInfoDo(msmtoolsUserInfoDo);
        return ResponseUtils.success();
    }

    @PostMapping("/userInfo/adduserinfo")
    public HashMap<String,Object> adduserinfo(@RequestBody MsmtoolsUserInfoVo msmtoolsUserInfoVo){
        String result = authService.adduserinfo(msmtoolsUserInfoVo);
        HashMap<String, Object> map = new HashMap<>();
        map.put("msg",result);
        map.put("status",0);
        return map;
    }

    //后台修改账户
    @PostMapping("/adduserinfo")
    public HashMap<String,Object> adduserinfoBack(@RequestBody MsmtoolsUserInfoVo msmtoolsUserInfoVo){
        String result = authService.adduserinfo(msmtoolsUserInfoVo);
        HashMap<String, Object> map = new HashMap<>();
        map.put("msg",result);
        map.put("status",0);
        return map;
    }

    @GetMapping("/userInfo/getUserByUserId")
    public BaseRestResponse<MsmtoolsUserInfoDto> getUserByUserId(@RequestParam(value = "userId") int userId){
        return authService.getUserByUserId(userId);
    }

    @GetMapping("/userInfo/getmenu")
    public List<MsmtoolsMenuDto> selectMenu(
            @RequestHeader(value = "Authorization", required = false) String authorization){
        log.info("getmenu::"+JSON.toJSONString(authorization));
        int userId = JwtUtil.verifyUserId(authorization);
        return authService.selectMenu(userId);
    }

    @GetMapping("/userInfo/getmenuinfo")
    public HashMap<String,Object> getMenuInfo(
            @RequestHeader(value = "Authorization", required = false) String authorization,
            @RequestParam(value = "key") String key){
        HashMap<String, Object> map = new HashMap<>();
        map.put("data",authService.getMenuInfoByMId(key));
        map.put("status",0);
        return map;
    }

    @GetMapping("/userInfo/getmenulist")
    public HashMap<String,Object> getmenulist(@RequestHeader(value = "Authorization", required = false) String authorization){

        List<MsmtoolsColumnsDto> menuColumns = getColumnsDos("msmtools_menu");
        List<MsmtoolsMenuAndChildrenDto> data = authService.getMenuAllandChildren();

        HashMap<String, Object> map = new HashMap<>();
        map.put("mapKey",menuColumns);
        map.put("data",data);
        return map;
    }

    @GetMapping("/userInfo/getuserlist")
    public HashMap<String,Object> getmenulist(
            @RequestHeader(value = "Authorization", required = false) String authorization,
            @RequestParam(value = "page") int page,
            @RequestParam(value = "pagesize") int pagesize){

        List<MsmtoolsColumnsDto> menuColumns = getColumnsDos("msmtools_user_info");

        List<MsmtoolsUserInfoDto> list = authService.selectAllMsmtoolsUserInfo(page,pagesize);

        int total = authService.selectAllCountMsmtoolsUserInfo();

        HashMap<String, Object> stringListHashMap = new HashMap<>();
        stringListHashMap.put("list",list);
        stringListHashMap.put("mapKey",menuColumns);

        HashMap<String, Object> map = new HashMap<>();
        map.put("total",total);
        map.put("status",0);
        map.put("data",stringListHashMap);
        return map;
    }


    @GetMapping("/userInfo/getpower")
    public HashMap<String,Object> getpower(@RequestHeader(value = "Authorization", required = false) String authorization){

        List<MsmtoolsColumnsDto> menuColumns = getColumnsDos("msmtools_power");

        List<MsmtoolsMenuAndChildrenDto> menu = authService.getMenuAllandChildren();

        List<MsmtoolsPowerDo> data = authService.selectAllMsmtoolsPower();

        HashMap<String, Object> map = new HashMap<>();
        map.put("mapKey",menuColumns);
        map.put("menu",menu);
        map.put("data",data);
        map.put("status",0);
        return map;
    }

    @GetMapping("/userInfo/getmessage")
    public HashMap<String,Object> getmessage(
            @RequestHeader(value = "Authorization", required = false) String authorization,
            @RequestParam(value = "page" ,required = false,defaultValue = "1") int page,
            @RequestParam(value = "pagesize",required = false,defaultValue = "10") int pagesize,
            @RequestParam(value = "name",required = false) String name,
            @RequestParam(value = "description",required = false) String description
    ){
        List<MsmtoolsColumnsDto> mapKey = getColumnsDos("msmtools_message");

        log.info("name::"+name+"description::"+description+"page::"+page+",pagesize::"+pagesize);
        List<MsmtoolsMessageDo> list = authService.selectAllMsmtoolsMessage(page,pagesize,name,description);
        log.info("list::"+JSON.toJSONString(list));

        int total = authService.selectAllCountMsmtoolsMessage();

        HashMap<String, Object> map = new HashMap<>();
        HashMap<String, Object> data = new HashMap<>();
        data.put("mapKey",mapKey);
        data.put("list",list);
        data.put("total",total);
        map.put("data",data);
        map.put("status",0);
        return map;
    }

    @PostMapping("/userInfo/addmenu")
    public HashMap<String,Object> addmenu(@RequestBody AddmenuVo addmenuVo){
        HashMap<String, Object> map = new HashMap<>();
        if(!RegexMatchesUtils.match(addmenuVo.getPath())){
            map.put("msg","path路径格式错误");
            map.put("status",0);
            return map;
        }
        String result = authService.addmenu(addmenuVo);
        map.put("msg",result);
        map.put("status",0);
        return map;
    }

    @PostMapping("/userInfo/editmenuinfo")
    public HashMap<String,Object> editmenuinfo(@RequestBody UpdateMenuVo updateMenuVo){
        HashMap<String, Object> map = new HashMap<>();
        if(!RegexMatchesUtils.match(updateMenuVo.getPath())){
            map.put("msg","路径格式错误");
            map.put("status",0);
            return map;
        }
        String result = authService.updateMenu(updateMenuVo);
        map.put("msg",result);
        map.put("status",0);
        return map;
    }

    @PostMapping("/userInfo/delmenu")
    public HashMap<String,Object> deleteMenuByMId(@RequestBody UpdateMenuVo updateMenuVo){
        String result = authService.deleteMenuByMId(updateMenuVo);
        HashMap<String, Object> map = new HashMap<>();
        map.put("msg",result);
        map.put("status",0);
        return map;
    }

    @PostMapping("/userInfo/edittype")
    public HashMap<String,Object> editType(@RequestBody UpdatePowerVo updatePowerVo){
        String result = authService.editType(updatePowerVo);
        HashMap<String, Object> map = new HashMap<>();
        map.put("msg",result);
        map.put("status",0);
        return map;
    }

    @PostMapping("/userInfo/addtype")
    public HashMap<String,Object> addtype(@RequestBody UpdatePowerVo updatePowerVo){
        String result = authService.addtype(updatePowerVo);
        HashMap<String, Object> map = new HashMap<>();
        map.put("msg",result);
        map.put("status",0);
        return map;
    }

    @GetMapping("/userInfo/searchVehicleData")
    public BaseRestResponse<VehicleWithSimResp> searchVehicleData(@RequestParam(value = "vin") String vin){
        return msDeviceFeignClient.findVehicleWithSimByVin(vin);
    }

    @PostMapping("/userInfo/msunicom/v1/queryBalance")
    public BaseRestResponse<Map> queryBalance(@RequestBody QueryBalanceVo queryBalanceVo){
        BaseRestResponse<BalanceUsedResponse> mnoResult = msunicomFeign.queryBalanceV1(queryBalanceVo.getProKey(),queryBalanceVo);
        log.info(JSON.toJSONString(mnoResult));

        Map<String, String> rsMap = new HashMap<>();
        if (mnoResult != null && mnoResult.getStatusCode().equals("0")) {
        JSONObject dataJSON = (JSONObject) JSON.toJSON(mnoResult.getData());
        rsMap = calFlowByUnicom(dataJSON);
        log.info(JSON.toJSONString(rsMap));
    }
        return ResponseUtils.success(rsMap);
    }

    @GetMapping("/userInfo/searchVehicleDataAll")
    public BaseRestResponse<SearchVehicleDataAllDto> searchVehicleDataAll(@RequestParam(value = "vin") String vin){
        return authService.searchVehicleDataAll(vin);
    }

    @PostMapping("/userInfo/getFeedBacklog")
    public BaseRestResponse<PageResult<NewFeedbackRecord>> getFeedBacklog(@RequestBody GetFeedbackVo getFeedbackVo){
        return authService.getFeedBacklog(getFeedbackVo);
    }

    @GetMapping ("/userInfo/getCreditBusinessVehicle")
    public BaseRestResponse<CreditConfigStatusResp> getCreditBusinessVehicle(@RequestParam(value = "vin") String vin){
        return authService.getCreditBusinessVehicle(vin);
    }

    @GetMapping ("/userInfo/getAddDataByMonth")
    public BaseRestResponse<List<AddDataByMonthDto>> getAddDataByMonth(
            @RequestParam(value = "startMonth") String startMonth,
            @RequestParam(value = "endMonth") String endMonth){
        return authService.getAddDataByMonth(startMonth,endMonth);
    }

    @PostMapping ("/userInfo/getAddDataByMonthAndVersion")
    public BaseRestResponse<AddDataByMonthAndVersionDto> getAddDataByMonthAndVersion(
            @RequestBody AddDataByMonthAndVersionVo addDataByMonthAndVersionVo){
        return authService.getAddDataByMonthAndVersion(addDataByMonthAndVersionVo);
    }


    private List<MsmtoolsColumnsDto> getColumnsDos(String menu) {

        List<MsmtoolsColumnsDo> menuColumns= authService.getmenulist(menu);
        ArrayList<MsmtoolsColumnsDto> list = new ArrayList<>();
        for (int i = 0; i < menuColumns.size(); i++) {
            MsmtoolsColumnsDto msmtoolsColumnsDto = new MsmtoolsColumnsDto();
            BeanUtils.copyProperties(menuColumns.get(i),msmtoolsColumnsDto);
            msmtoolsColumnsDto.setHidden(false);
            if(Objects.equals(menuColumns.get(i).getKey(), "del_flag")) menuColumns.remove(i);
            list.add(msmtoolsColumnsDto);
        }
        return list;
    }

    /**
     * 计算unicom流量使用情况
     * @param dataJSON
     * @return
     */
    private Map<String, String> calFlowByUnicom(JSONObject dataJSON) {

        // 流量限额
        double quota = 0.00D;
        // 已使用
        double monthUsedFlow = 0.00D;
        // 剩余流量
        double monthBalanceFlow = 0.00D;

        JSONObject unicomJSON = dataJSON.getJSONObject("body");
        JSONArray summaryArray = unicomJSON.getJSONArray("summary");
        for (Object temp : summaryArray) {
            JSONObject summary = (JSONObject) temp;
            if (summary.containsKey("packageGroup")
                    && summary.getString("packageGroup").equals("BASIC")) {

                double basicQuota = summary.getBigDecimal("trafficQuota").doubleValue();
                double basicUsage = summary.getBigDecimal("trafficUsage").doubleValue();
                quota += basicQuota;
                monthUsedFlow += basicUsage;
            }
            if (summary.containsKey("packageGroup")
                    && summary.getString("packageGroup").equals("ADDITIONAL")) {
                double addQuota = summary.getBigDecimal("trafficQuota").doubleValue();
                double addUsage = summary.getBigDecimal("trafficUsage").doubleValue();
                quota += addQuota;
                monthUsedFlow += addUsage;
            }
        }
        // 剩余流量
        monthBalanceFlow = (quota - monthUsedFlow);
        Map<String, String> rsMap = new HashMap<>();
        rsMap.put("monthUsedFlow", new BigDecimal(monthUsedFlow / 1024).setScale(3, BigDecimal.ROUND_DOWN).toString());
        rsMap.put("monthBalanceFlow", new BigDecimal(monthBalanceFlow / 1024).setScale(3, BigDecimal.ROUND_DOWN).toString());
        return rsMap;
    }

    public static void main(String[] args) throws Exception {
//        String account = "admin";
//        String pswd = "123456";
//
//        HashMap<String,Object> res = new HashMap<>();
//
//        //MD5加密
//        ByteSource credentialsSalt = ByteSource.Util.bytes(account);
//        Object obj = new SimpleHash("MD5", pswd, credentialsSalt, 1);
//        System.out.println(obj);

        String vin = "LDP29H926PM002589";
        Map<String,String> map = new HashMap<>();
        map.put("vin",vin);
        log.info("fullKeyList vin:{}", vin);
        String DkServer =  "https://idp-prd.dfiov.com.cn";
        String fullKeyListPath ="/tsp/apis/v4/idk/fullKeyList";
        String appSecret = "1ea2362eba7901395425212d76360177d9be1af797677995";
        String appId = "9767799567493d4a";

            long timestamp = System.currentTimeMillis();
            String[] encryptDataAndSign = SignUtils.encryptDataAndSign(JSON.toJSONString(map), timestamp, appSecret);
            String url = DkServer + fullKeyListPath;
            log.info("fullKeyList timestamp:{}", timestamp);
            log.info("fullKeyList sign:{}", encryptDataAndSign[1]);
            log.info("fullKeyList url:{}",  url);
            log.info("fullKeyList body:{}", encryptDataAndSign[0]);

            String result = HttpRequest.post(url).header("Content-Type", "application/json")
                    .header("appid", appId)
                    .header("timestamp", String.valueOf(timestamp))
                    .header("x-ingeek-sign", encryptDataAndSign[1])
                    .body(encryptDataAndSign[0])
                    .execute().body();
            log.info("fullKeyList result:{}",result);
            DkResult dkResult = JSONObject.parseObject(result, DkResult.class);
            log.info("fullKeyList dkResult:{}",result);
            if (dkResult.getCode() == 0) {
                //return new BaseRestResponse<>(Constants.SUCCESS_CODE0, Constants.SUCCESS_DESCRIPTION, dkResult.getData());
            }else{
                //throw new BusinessException(dkResult.getCode() + "", dkResult.getMsg());
            }
    }


    /**
     * 导出乘用车激活数据
     */
    @RequestMapping(value = "/userInfo/exportAddDataByMonthAndVersion", method = RequestMethod.POST)
    @ApiOperation(value = "导出乘用车激活数据", httpMethod = "POST")
    public void exportAddDataByMonthAndVersion(
            @RequestBody ExportDataByMonthAndVersionVo exportDataByMonthAndVersionVo,
            HttpServletResponse response) {
        authService.exportAddDataByMonthAndVersionV2(exportDataByMonthAndVersionVo,response);
    }


}
